﻿using System;
using System.Collections.Generic;
using System.Windows.Input;
using System.Linq;
using System.Text;

namespace Com.CodePlex.SPC3.SPbAM.Controller {

	//http://www.wpftutorial.net/DelegateCommand.html
	/*
	 * A better example I suggest is this RelayCommand: 
	 * The implementation of ICommand.CanExecuteChanged is relying on the wpf's 
	 * CommandManager.Requery suggested event. This will improve binding scenarios.  
	 * */
	public class DelegateCommand<T> : ICommand {

		private readonly Predicate<T> _canExecute;
		private readonly Action<T> _execute;

		public event EventHandler CanExecuteChanged;

		public DelegateCommand(Action<T> execute)
			: this(execute, null) {
		}

		public DelegateCommand(Action<T> execute, Predicate<T> canExecute) {
			_execute = execute;
			_canExecute = canExecute;
		}

		public bool CanExecute(object parameter) {
			return CanExecute((T)parameter);
		}

		public bool CanExecute(T parameter) {
			if (_canExecute == null) {
				return true;
			}
			return _canExecute(parameter);
		}

		public void Execute(object parameter) {
			Execute((T)parameter);
		}

		public void Execute(T parameter) {
			_execute(parameter);
		}

		public void RaiseCanExecuteChanged() {
			if (CanExecuteChanged != null) {
				CanExecuteChanged(this, EventArgs.Empty);
			}
		}
	}

	//http://waf.codeplex.com/
	public class DelegateCommand2 : ICommand {
		private readonly Action<object> execute;
		private readonly Func<object, bool> canExecute;


		/// <summary>
		/// Occurs when changes occur that affect whether or not the command should execute.
		/// </summary>
		public event EventHandler CanExecuteChanged;


		/// <summary>
		/// Initializes a new instance of the <see cref="DelegateCommand"/> class.
		/// </summary>
		/// <param name="execute">Delegate to execute when Execute is called on the command.</param>
		public DelegateCommand2(Action execute) : this(execute, null) { }

		/// <summary>
		/// Initializes a new instance of the <see cref="DelegateCommand"/> class.
		/// </summary>
		/// <param name="execute">Delegate to execute when Execute is called on the command.</param>
		public DelegateCommand2(Action<object> execute) : this(execute, null) { }

		/// <summary>
		/// Initializes a new instance of the <see cref="DelegateCommand"/> class.
		/// </summary>
		/// <param name="execute">Delegate to execute when Execute is called on the command.</param>
		/// <param name="canExecute">Delegate to execute when CanExecute is called on the command.</param>
		public DelegateCommand2(Action execute, Func<bool> canExecute)
			: this(execute != null ? p => execute() : (Action<object>)null, canExecute != null ? p => canExecute() : (Func<object, bool>)null) { }

		/// <summary>
		/// Initializes a new instance of the <see cref="DelegateCommand"/> class.
		/// </summary>
		/// <param name="execute">Delegate to execute when Execute is called on the command.</param>
		/// <param name="canExecute">Delegate to execute when CanExecute is called on the command.</param>
		public DelegateCommand2(Action<object> execute, Func<object, bool> canExecute) {
			if (execute == null) { throw new ArgumentNullException("execute"); }

			this.execute = execute;
			this.canExecute = canExecute;
		}


		/// <summary>
		/// Defines the method that determines whether the command can execute in its current state.
		/// </summary>
		/// <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
		/// <returns>
		/// true if this command can be executed; otherwise, false.
		/// </returns>
		public bool CanExecute(object parameter) {
			return canExecute != null ? canExecute(parameter) : true;
		}

		/// <summary>
		/// Defines the method to be called when the command is invoked.
		/// </summary>
		/// <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
		/// <exception cref="InvalidOperationException">The <see cref="CanExecute"/> method returns <c>false.</c></exception>
		public void Execute(object parameter) {
			if (!CanExecute(parameter)) {
				throw new InvalidOperationException("The command cannot be executed because the canExecute action returned false.");
			}

			execute(parameter);
		}

		/// <summary>
		/// Raises the <see cref="E:CanExecuteChanged"/> event.
		/// </summary>
		public void RaiseCanExecuteChanged() {
			OnCanExecuteChanged(EventArgs.Empty);
		}

		/// <summary>
		/// Raises the <see cref="E:CanExecuteChanged"/> event.
		/// </summary>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		protected virtual void OnCanExecuteChanged(EventArgs e) {
			EventHandler canExecuteChanged = CanExecuteChanged;
			if (canExecuteChanged != null) { canExecuteChanged(this, e); }
		}
	}
}
